package com.sp.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sp.exception.BusinessException;
import com.sp.mapper.EmployeeRoleAndPermissionMapper;
import com.sp.mapper.PermissionMapper;
import com.sp.model.dto.PermissionDTO;
import com.sp.model.entity.Permission;
import com.sp.model.entity.User;
import com.sp.service.PermissionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import static com.sp.constant.PermissionMessageConstant.*;
import static com.sp.constant.RedisConstant.EMPLOYEE_PERMISSIONS;

/**
 * @author tong
 * @date 2024/4/14 14:01
 */
@Service
public class PermissionServiceImpl implements PermissionService {

    @Autowired
    private PermissionMapper permissionMapper;

    @Autowired
    private EmployeeRoleAndPermissionMapper employeeRoleAndPermissionMapper;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Transactional
    @Override
    public boolean addPermission(PermissionDTO permissionDTO) {
        if (permissionDTO == null || StrUtil.isBlank(permissionDTO.getKeyword()) ||
                StrUtil.isBlank(permissionDTO.getName()) || StrUtil.isBlank(permissionDTO.getDescription())) {
            throw new BusinessException(ADD_PERMISSION_FAIL + "：" + PARAM_ERROR);
        }

        stringRedisTemplate.delete(EMPLOYEE_PERMISSIONS);

        return permissionMapper.insert(BeanUtil.copyProperties(permissionDTO, Permission.class)) == 1;
    }

    @Transactional
    @Override
    public boolean updatePermission(PermissionDTO permissionDTO) {
        if (permissionDTO == null || permissionDTO.getId() == null) {
            throw new BusinessException(UPDATE_PERMISSION_FAIL + "：" + PARAM_ERROR);
        }

        stringRedisTemplate.delete(EMPLOYEE_PERMISSIONS);

        return permissionMapper.updateById(BeanUtil.copyProperties(permissionDTO, Permission.class)) == 1;
    }

    @Transactional
    @Override
    public boolean deletePermissions(List<Integer> ids) {
        for (Integer id : ids) {
            if (employeeRoleAndPermissionMapper.countByPermissionId(id) > 0) {
                throw new BusinessException(DELETE_PERMISSION_FAIL + "：具体权限存在关联");
            }
        }

        stringRedisTemplate.delete(EMPLOYEE_PERMISSIONS);

        return permissionMapper.deleteBatchIds(ids) == ids.size();
    }

    @Override
    public IPage<Permission> page(Integer currentPage, Integer pageSize, PermissionDTO permissionDTO) {
        if (currentPage == null) {
            currentPage = 1;
        }

        if (pageSize == null) {
            pageSize = 10;
        }

        //条件查询
        QueryWrapper<Permission> queryWrapper = new QueryWrapper<>();
        if (permissionDTO != null) {
            queryWrapper.like(StrUtil.isNotBlank(permissionDTO.getName()), "`p`.`name`", permissionDTO.getName())
                    .like(StrUtil.isNotBlank(permissionDTO.getKeyword()), "`p`.`keyword`", permissionDTO.getKeyword())
                    .like(StrUtil.isNotBlank(permissionDTO.getDescription()), "`p`.`description`", permissionDTO.getDescription());
        }
        IPage<User> page = new Page<>(currentPage, pageSize);

        return permissionMapper.page(page, queryWrapper);
    }

    @Override
    public List<Permission> selectAll() {
        return this.selectAllFromRedis();
    }

    /**
     * 从缓存获取所有具体权限
     *
     * @return
     */
    private List<Permission> selectAllFromRedis() {
        String json = stringRedisTemplate.opsForValue().get(EMPLOYEE_PERMISSIONS);
        if (StrUtil.isNotBlank(json)) {
            return JSONObject.parseArray(json, Permission.class);
        }

        // 缓存不存在
        List<Permission> permissions = permissionMapper.selectAll();
        stringRedisTemplate.opsForValue().set(EMPLOYEE_PERMISSIONS, JSONObject.toJSONString(permissions), 1, TimeUnit.DAYS);
        return permissions;
    }

    @Override
    public Map<Integer, Permission> selectAllMap() {
        return this.selectAllMapFromRedis();
    }

    /**
     * 从缓存中获取所有具体权限 map
     *
     * @return
     */
    private Map<Integer, Permission> selectAllMapFromRedis() {
        List<Permission> permissions = this.selectAllFromRedis();
        HashMap<Integer, Permission> hashMap = new HashMap<>();
        for (Permission permission : permissions) {
            hashMap.put(permission.getId(), permission);
        }
        return hashMap;
    }

}
